<template>
  <div class="app-container">
    <!-- <div slot="header" class="clearfix">
      <span>惩罚系数</span>
    </div> -->
    <div class="block">
      <el-form label-position="right" ref="form" :rules="rules"  label-width="120px" :model="formLabelAlign">
        <el-card class="box-card">
          <el-row :gutter="24">
            <el-col :span="6">
              <el-form-item label="选择分行">
                <el-select v-model="formLabelAlign.orgType" @change="orgTypeChange" placeholder="请选择" size="mini">
                  <el-option
                    v-for="item in orgTypeOptions"
                    :key="item.subBankCode"
                    :label="item.subBankName"
                    :value="item.subBankCode">
                  </el-option>
                </el-select>
              </el-form-item>
            </el-col>
            <el-col :span="6">
              <el-form-item label="topP">
                <template v-slot:label>
                  <el-tooltip
                  content="控制模型生成过程中考虑的词汇范围，使用累计概率选择候选词，直到累计概率超过给定的阈值。该参数也可以控制生成结果的多样性，它基于累积概率选择候选词，直到累计概率超过给定的阈值为止。取值范围(1e-6, 1.0]，默认值1.0，可以为null。不建议同时修改该值与temperature。"
                  effect="dark" placement="top">
                    <span>topP</span>
                  </el-tooltip>
                </template>
                <el-input-number size="mini" v-model="formLabelAlign.topP"
                :min="0.0" :max="1.0" :step="0.01"></el-input-number>
              </el-form-item>
            </el-col>
            <el-col :span="6">
              <el-form-item label="topK">
                <template v-slot:label>
                  <el-tooltip content="控制模型生成过程中考虑的词汇范围，只从概率最高的k个候选词中选择。取值范围-1或（0, 2147483647]，可以为null。"
                  effect="dark" placement="top">
                    <span>topK</span>
                  </el-tooltip>
                </template>
                <el-input-number size="mini" v-model="formLabelAlign.topK"
                :min="-1" :max="1000" :step="1"></el-input-number>
              </el-form-item>
            </el-col>
            <el-col :span="6">
              <el-form-item label="maxTokens">
                <template v-slot:label>
                  <el-tooltip content="允许推理生成的最大token个数。实际产生的token数量同时受到配置文件maxIterTimes参数影响，推理token个数小于或等于min(maxIterTimes, maxTokens)。"
                  effect="dark" placement="top">
                    <span>maxTokens</span>
                  </el-tooltip>
                </template>
                <el-input-number size="mini" v-model="formLabelAlign.maxTokens"
                :min="1" :max="2000" :step="1"></el-input-number>
              </el-form-item>
            </el-col>
          </el-row>
          <el-row :gutter="24">
            <el-col :span="6">
              <el-form-item label="presencePenalty">
                <template v-slot:label>
                  <el-tooltip
                  content="presencePenalty 存在惩罚介于-2.0和2.0之间，它影响模型如何根据到目前为止是否出现在文本中来惩罚新token。正值将通过惩罚已经使用的词，增加模型谈论新主题的可能性。不建议同时修改该值与repetitionPenalty或frequencyPenalty。"
                  effect="dark" placement="top">
                    <span>存在惩罚</span>
                  </el-tooltip>
                </template>
                <el-input-number size="mini" v-model="formLabelAlign.presencePenalty"
                :min="-2.0" :max="2.0" :step="0.01"></el-input-number>
              </el-form-item>
            </el-col>
            <el-col :span="6">
              <el-form-item label="frequencyPenalty">
                <template v-slot:label>
                  <el-tooltip
                  content="frequencyPenalty 频率惩罚介于-2.0和2.0之间，它影响模型如何根据文本中词汇的现有频率惩罚新词汇。正值将通过惩罚已经频繁使用的词来降低模型一行中重复用词的可能性。不建议同时修改该值与repetitionPenalty或presencePenalty。"
                  effect="dark" placement="top">
                    <span>频率惩罚</span>
                  </el-tooltip>
                </template>
                <el-input-number size="mini" v-model="formLabelAlign.frequencyPenalty"
                :min="-2.0" :max="2.0" :step="0.01"></el-input-number>
              </el-form-item>
            </el-col>
            <el-col :span="6">
              <el-form-item label="repetitionPenalty">
                <template v-slot:label>
                  <el-tooltip
                  content="repetitionPenalty 重复惩罚用于减少在文本生成过程中出现重复片段的概率。它对之前已经生成的文本进行惩罚，使得模型更倾向于选择新的、不重复的内容。取值范围(0.0, 2.0]，默认值1.0，可以为null。不建议同时修改该值与presencePenalty或frequencyPenalty。"
                  effect="dark" placement="top">
                    <span>重复惩罚</span>
                  </el-tooltip>
                </template>
                <el-input-number size="mini" v-model="formLabelAlign.repetitionPenalty"
                :min="0.0" :max="2.0" :step="0.01"></el-input-number>
              </el-form-item>
            </el-col>
            <el-col :span="6">
                <el-form-item label="temperature">
                  <template v-slot:label>
                    <el-tooltip
                    content="temperature 控制生成的随机性，较高的值会产生更多样化的输出。取值范围大于或等于0.0，默认值1.0，可以为null。取值越大，结果的随机性越大。推荐使用大于或等于0.001的值，小于0.001可能会导致文本质量不佳。不建议同时修改该值与topP。"
                    effect="dark" placement="top">
                      <span>温度</span>
                    </el-tooltip>
                  </template>
                  <el-input-number size="mini" v-model="formLabelAlign.temperature"
                  :min="0" :max="10.0" :step="0.01"></el-input-number>
                </el-form-item>
            </el-col>
          </el-row>
        </el-card>
        <el-card class="box-card" style="margin-top: 10px;">
          <el-row :gutter="24">
            <el-col :span="8">
              <el-card style="width: 100%;min-height: 400px;">
                <div style="display: flex;">
                  <el-select v-model="fileType" @change="fileTypeChange" placeholder="文件类型" size="mini">
                    <el-option
                      v-for="item in fileTypeOptions"
                      :key="item.value"
                      :label="item.label"
                      :value="item.value">
                    </el-option>
                  </el-select>
                  <el-button style="margin-left: 10px;" size="small" type="success" @click="submitUpload">上传到服务器</el-button>
                </div>
                <div style="max-height: 350px;overflow: auto;margin-top: 5px;">
                  <el-upload
                    v-if="fileType == 'images'"
                    class="upload-demo"
                    ref="upload"
                    action=""
                    :on-remove="handleRemove"
                    :before-remove="beforeRemove"
                    :on-preview="handlePictureCardPreview"
                    multiple
                    :limit="10"
                    :on-exceed="handleExceed"
                    :file-list="fileList"
                    :auto-upload="false"
                    name="files"
                    :with-credentials="true"
                    :on-change="handleChange"
                    :list-type="listType"
                    :accept="acceptImages.join(',')"
                    >
                    <el-button slot="trigger" size="small" type="primary">选取文件</el-button>
                    <!-- 上传提示 -->
                    <div class="el-upload__tip" slot="tip">
                      请上传
                      <template v-if="fileSize">大小不超过<b style="color: #f56c6c">{{ fileSize }}KB</b><br></template>
                      <template v-if="fileTypelist">格式为<b style="color: #f56c6c">{{ fileTypelist.join("/") }}</b> </template>
                      的文件
                    </div>
                  </el-upload>
                  <el-upload
                    v-if="fileType == 'video'"
                    class="upload-demo"
                    ref="upload"
                    action=""
                    :on-remove="handleRemove"
                    :before-remove="beforeRemove"
                    :on-preview="handlePictureCardPreview"
                    :limit="1"
                    :on-exceed="handleExceed"
                    :file-list="fileList"
                    :auto-upload="false"
                    name="files"
                    :with-credentials="true"
                    :on-change="handleChange"
                    :list-type="listType"
                    :accept="acceptVideo.join(',')"
                    >
                    <el-button slot="trigger" size="small" type="primary">选取文件</el-button>
                    <!-- 上传提示 -->
                    <div class="el-upload__tip" slot="tip">
                      请上传
                      <template v-if="videoFileSize">大小不超过<b style="color: #f56c6c">{{ videoFileSize }}MB</b><br></template>
                      <template v-if="videoFileTypeList">格式为<b style="color: #f56c6c">{{ videoFileTypeList.join("/") }}</b> </template>
                      的文件
                    </div>
                  </el-upload>
                  <video v-if="videoPreview && fileType == 'video'" :src="videoPreview" controls style="width: 100%; margin-top: 10px;">
                    Your browser does not support the video tag.
                  </video>
                </div>
              </el-card>
            </el-col>
            <el-col :span="8">
              <el-card style="width: 100%;min-height: 400px;">
                <div>
                  已上传文件：{{ upload_file_id }}
                </div>
                <el-input
                  style="margin-top: 10px;"
                  type="textarea"
                  :autosize="{ minRows: 15, maxRows: 15}"
                  placeholder="请输入内容"
                  v-model="formLabelAlign.prompt">
                </el-input>
                <div style="display: flex; justify-content: flex-end;">
                  <el-button style="margin-top: 10px;" size="small" type="success" @click="submitPrompt">大模型生成</el-button>
                </div>
              </el-card>
            </el-col>
            <el-col :span="8">
              <el-card style="width: 100%;min-height: 400px;">
                <div>
                  大模型分析结果：
                </div>
                <el-input
                  style="margin-top: 10px;"
                  disabled
                  type="textarea"
                  :autosize="{ minRows: 15, maxRows: 15}"
                  v-text="llm_result_text">
                </el-input>
              </el-card>
            </el-col>
          </el-row>
        </el-card>
      </el-form>
    </div>
    <el-dialog :visible.sync="dialogVisible">
      <img width="100%" :src="dialogImageUrl" alt="">
    </el-dialog>
  </div>
</template>

<script>
import { aiModel, uploadFile, queryBranchBankConfig } from "@/api/modelTest/llmTest";

export default {
  name: "LlmTest",
  data() {
    return {
      dialogImageUrl: '',
      dialogVisible: false,
      formLabelAlign: {
        presencePenalty: -0.43,
        frequencyPenalty: 0.1,
        repetitionPenalty: 1.0,
        orgType: "",
        topP: 0.1,
        topK: -1,
        temperature: 0.001,
        maxTokens: 256,
        prompt: ""
      },
      fileType: "images",
      listType: 'picture-card',
      // 文件类型, 例如
      fileTypelist: ['png', 'jpg', 'jpeg'],
      videoFileTypeList: ['mp4'],
      acceptImages: ['image/png', 'image/jpeg'],
      acceptVideo: ['video/mp4', 'video/avi'],
      videoPreview: "",
      // 图片大小限制(KB)
      fileSize: 800,
      // 图片大小限制(MB)
      videoFileSize: 100,
      orgTypeOptions: [],
      upload_file_id: "",
      fileList: [],
      llm_result_text: "",
      // 是否显示提示
      isShowTip: {
        type: Boolean,
        default: true
      },
      rules: {
        prompt: [
          { required: true, message: "提示词不能为空", trigger: "blur" }
        ]
      },
      fileTypeOptions: [{
        label: "图片测试",
        value: "images"
      }, {
        label: "视频测试",
        value: "video"
      }]
    };
  },
  created() {
    queryBranchBankConfig().then(response => {
      this.orgTypeOptions = response.data;
      this.formLabelAlign.orgType = this.orgTypeOptions[0].subBankCode;
    });
  },
  methods: {
    submitPrompt () {
      // this.$refs.upload.submit();
      if (this.isGenerate) {
        this.$message.warning("大模型正在生成中，请勿重复提交！");
        return false
      }
      if (!this.upload_file_id) {
        this.$message.warning("请先上传文件");
        return false
      }

      if (!this.formLabelAlign.prompt) {
        this.$message.warning("提示词不能为空");
        return false
      }
      this.$refs["form"].validate(valid => {
        if (valid) {
          const formData = Object.assign(this.formLabelAlign, {
            fileId: this.upload_file_id,
            branchBank: this.formLabelAlign.orgType
          });
          this.llm_result_text = ""
          this.isGenerate = true;
          aiModel(formData).then(response => {
            this.$message.success("生成成功");
            this.llm_result_text = response.data;
          }).catch(error => {
            this.$message.success("生成失败");
          }).finally(() => {
            this.isGenerate = false;
          });
        }
      });
    },
    handlePictureCardPreview(file) {
      this.dialogImageUrl = file.url;
      this.dialogVisible = true;
    },
    orgTypeChange () {
      this.videoPreview = ""
      this.fileList = []
    },
    fileTypeChange(data) {
      if (this.fileType == "images") {
        this.listType = 'picture'
      } else {
        this.listType = 'text'
      }
      this.videoPreview = ""
      this.upload_file_id = ""
      this.fileList = []
    },
    handleRemove(file, fileList) {
      console.log(file, fileList);
      this.fileList = fileList
      this.upload_file_id = ""
      if (this.fileType == "video"){
        this.videoPreview = ""
      }
    },
    handlePreview(file) {
      console.log(file);
    },
    handleExceed(files, fileList) {
      this.$message.warning(`选择文件超限，本次选择了 ${files.length} 个文件，共选择了 ${files.length + fileList.length} 个文件`);
    },
    handleChange(files, fileList) {
      this.videoPreview = ""
      this.fileList = fileList.map((file) => {
        if (this.fileType === "images" && file && file.raw && file.raw.type.startsWith("image/")) {
          return file
        }else if (this.fileType === "video" && file && file.raw && file.raw.type.startsWith("video/")) {
          this.videoPreview = URL.createObjectURL(file.raw);
          return file
        }
      })

    },
    submitUpload() {
      console.log("submitUpload");
      if (this.fileList.length === 0) {
        this.$message.warning("请先选择文件");
        return false
      }
      if (!this.formLabelAlign.orgType){
        this.$message.warning("请先选择分行");
        return false
      }
      const formData = new FormData();

      let bigFileSize = false
      let bigFileSizeText = ''

      // 校检图片文件大小
      if (this.fileType === "images" && this.fileSize) {
        this.fileList.forEach((file) => {
          // formData.append('files', file.raw); // `file.raw` is the actual File object
          if(file && file.raw && (file.raw.size / 1024 > this.fileSize)){
            bigFileSize = true
            bigFileSizeText = `上传文件大小不能超过 ${this.fileSize} KB!`
            return false;
          }
        });
      }

      if (this.fileType === "video" && this.videoFileSize) {
        this.fileList.forEach((file) => {
          // formData.append('files', file.raw); // `file.raw` is the actual File object
          if(file && file.raw && (file.raw.size / 1024 / 1024 > this.videoFileSize)){
            bigFileSize = true
            bigFileSizeText = `上传文件大小不能超过 ${this.videoFileSize} MB!`
            return false;
          }
        });
      }

      if (bigFileSize) {
        this.$modal.msgError(bigFileSizeText);
        return false
      }

      this.fileList.forEach((file) => {
        formData.append('files', file.raw); // `file.raw` is the actual File object
      });
      formData.append('branchBank', this.formLabelAlign.orgType);

      // axios.post(`${process.env.VUE_APP_BASE_API}/prompt/uploadFile`, formData, {
      //   headers: {
      //     'Content-Type': 'multipart/form-data'
      //   },
      //   withCredentials: true
      // })
      uploadFile(formData).then(response => {
        console.log('File uploaded successfully:', response.data);
        this.upload_file_id = response.data;
      })
      .catch(error => {
        this.$message.warning("上传失败");
      });
    },
    beforeRemove(file, fileList) {
      return this.$confirm(`确定移除 ${ file.name }？`);
    }
  }
};
</script>
